urllibだけである程度HTTPリクエストを頑張る
AWS LambdaからいくつかのWeb APIを呼び出すコードをrequestsなどの外部ライブラリを使わずにささっと書きたくて、標準ライブラリであるurllibを色々使ってみたのでそのメモです。
使ったもの
- Python: 3.7.6
- ライブラリ: urllib
GET
GETの場合はurlopenに直接URLを指定するか、下記のようにRequestを生成します。
認証ヘッダーなどつけたい場合がほとんどだと思うのでRequestを使ってみます。
from urllib import request, parse import json from pprint import pprint ## GET get_header = {'Authorization': 'XXXXXXXXXX'} get_req = request.Request('https://httpbin.org/get', headers=get_header) with request.urlopen(get_req, headers=get_header) as res: # resは http.client.HTTPResponse body = json.loads(res.read()) # レスポンスボディ headers = res.getheaders() # ヘッダー(dict) status = res.getcode() # ステータスコード pprint(headers) pprint(status) pprint(body)
POST
POSTに限らずGET以外のHTTPメソッドの場合はmethod
パラメータを指定します。
そしてリクエストボディはdata
で指定します。ドキュメントによるとこのパラメータは・・・
The supported object types include bytes, file-like objects, and iterables.
ということなので、stringの場合はencode
してbytesに変換します。formの送信の場合は下記のようになります。
JSONをPOSTする場合は同様にJSON文字列をencodeします。
## POST(form) post_form_data = parse.urlencode({'key': 'value'}) post_form_headers = {'content-type': 'application/x-www-form-urlencoded'} post_req = request.Request('https://httpbin.org/post', data=post_form_data.encode(), method='POST') with request.urlopen(post_req) as res: body = json.loads(res.read()) # レスポンスボディ pprint(body)
Basic認証
Basic認証もライブラリなしで頑張ってみます。
ハンドラを使った方法もサポートされているのですが、ズボラなのでヘッダーを組み立ててみました。
## BASIC認証 import base64 basic_auth_token = base64.b64encode('user:password'.encode()).decode() basic_auth_header = {'Authorization': 'Basic ' + basic_auth_token} basic_auth_req = request.Request('https://httpbin.org/basic-auth/user/password', headers=basic_auth_header) with request.urlopen(basic_auth_req) as res: body = json.loads(res.read()) # レスポンスボディ pprint(body)
レスポンスステータスが4XX, 5XXの時
urllib.error.HTTPErrorがスローされるので必要に応じてハンドリングします。 下記の例ではいずれもHTTPErrorがスローされてexcept内が実行されます。
from urllib import request, parse, error for code in [300, 400, 500]: req = request.Request('https://httpbin.org/status/{}'.format(code)) try: with request.urlopen(req) as res: pprint(res.getcode()) except error.HTTPError as e: pprint(e)
まとめ
urllibだけでHTTPリクエストを頑張ってみました。